/**************************************************************************//**
\file  hih5031.c

\brief This module is used for measure humidity value.

\author
	Satxo

\internal
  History:
    29/06/07 R. Rodrigues - Created
******************************************************************************/
/******************************************************************************
                   Includes section
******************************************************************************/
#include <hih5031.h>
#include <bspadc.h>
#include <appTimer.h>
#include <bspTaskManager.h>
#include <types.h>

/******************************************************************************
                   Define(s) section
******************************************************************************/

#define HIH5031_DELAY						10	// in milliseconds

#define HIH5031_STATE_QUEUE_LEN				8	// state queue length

/******************************************************************************
                   Global variables section
******************************************************************************/
// The flow control variable
static Hih5031Control_t hih5031Control;

// hods a FIFO queue of task for the bspHIH5031Handler task handler function
static Hih5031States_t hih5031State[HIH5031_STATE_QUEUE_LEN] = { HIH5031_IDLE };

// Timer structure, used to make the delays needed for A2D conversion
static HAL_AppTimer_t hih5031Delay;

uint16_t value; // Auxiliary measure

/******************************************************************************
                   Implementations section
******************************************************************************/
/**************************************************************************//**
\brief  Adds a new task to the task queue, FIFO style.

\param[in]
  task - the task to be queued.

\return
  BC_FAIL - if the queue if full, has more than HIH5031_STATE_QUEUE_LEN tasks
  BC_SUCCESS - other case.

******************************************************************************/
result_t hih5031PushTask(Hih5031States_t task)
{	
	uint8_t i;
	for( i=0; i < HIH5031_STATE_QUEUE_LEN-1; i++)
	{
		/* the queue is filled with IDLE tasks by default.
		The first IDLE task found will be replaced by the task we want to add. */
		if( hih5031State[i] == HIH5031_IDLE )
		{
			hih5031State[i] = task;
			return BC_SUCCESS;
		}
	}
	return BC_FAIL;
}

/**************************************************************************//**
\brief	Returns the first task to be executed from the queue, FIFO style.

\return
	the task in queue to be executed.
******************************************************************************/
Hih5031States_t hih5031PopTask(void)
{	
	uint8_t i;
	Hih5031States_t task = hih5031State[0];
	
	for( i=0; i < HIH5031_STATE_QUEUE_LEN-1; i++)
	{
		hih5031State[i] = hih5031State[i+1];
	}
	return task;
}


/**************************************************************************//**
\brief  Opens the component to use.

\return
  BC_SUCCESS - the component is ready to been use.
  BC_FAIL - otherwise.

******************************************************************************/
result_t openHih5031(void)
{
	if (HIH5031_IDLE == hih5031State[0])
	{
		//openBspAdc();
	    return BC_SUCCESS;
	}
		
	return BC_FAIL;
}


/**************************************************************************//**
\brief  Performs the test if the component have completed request.

\return
  BC_FAIL - the previous request is not completed.
  BC_SUCCESS - otherwise.
******************************************************************************/
result_t closeHih5031(void)
{
  if (HIH5031_IDLE == hih5031State[0])
  {
		//closeBspAdc();
		return BC_SUCCESS;
  }	

  return BC_FAIL;
}

/**************************************************************************//**
\brief Reads data from hih5031 humidity sensor.

\param[in]
  f - callback method.
\param[in]
  result - the result of the requested operation.
           true - operation finished successfully,
           false - some error has occurred.
\param[in]
  data - sensor data.
\return
  BC_FAIL - the previous request was not completed.
  BC_SUCCESS - other case.
******************************************************************************/
result_t readHih5031Data(void (*f)(bool result, uint16_t data))
{	
	if (HIH5031_IDLE != hih5031State[0])
		return BC_FAIL;

	if (!f)
		return BC_FAIL;
		
	hih5031Control.hih5031Callback = f;

	if (BC_FAIL == hih5031PushTask(HIH5031_WAIT))
		return BC_FAIL;
	if (BC_FAIL == hih5031PushTask(HIH5031_GET_HUMIDITY))
		return BC_FAIL;
	if (BC_FAIL == hih5031PushTask(HIH5031_RETURN))
		return BC_FAIL;
	bspPostTask(BSP_HUMIDITY);
	
	return BC_SUCCESS;
}

/**************************************************************************//**
\brief  Starts ADC request on battery channel. XXXXXXXXXXXX
******************************************************************************/
void hih5031DataCallback(uint16_t data)
{
	hih5031Control.hih5031Data = data * 3ul; // Board specific multiplier
	if (data == 0)
		hih5031Control.hih5031Result = false;
	else
		hih5031Control.hih5031Result = true;
	bspPostTask(BSP_HUMIDITY);
}

/**************************************************************************//**
\brief HIH5031 Task Handler.
******************************************************************************/
void bspHIH5031Handler(void)
{
	Hih5031States_t task;
	task = hih5031PopTask();

	if (task ==	HIH5031_IDLE)
	{	// IDLE state, does nothing
		return;
	}

	if (task ==	HIH5031_RETURN)
	{	// if queue is empty, call top layer task handler, else continue to next task
		if (HIH5031_IDLE == hih5031State[0])
			hih5031Control.hih5031Callback(hih5031Control.hih5031Result, hih5031Control.hih5031Data);
		else
			bspPostTask(BSP_HUMIDITY);

		return;
	} // RETURN

	if (task ==	HIH5031_WAIT)
	{	// wait HIH5031_WAIT milliseconds to jump to the next task
		hih5031Delay.interval = HIH5031_DELAY;					// Timer interval in milliseconds
		hih5031Delay.mode     = TIMER_ONE_SHOT_MODE;			// One shot mode (TIMER_REPEAT_MODE or TIMER_ONE_SHOT_MODE)
		hih5031Delay.callback = bspHIH5031Handler;				// Callback function for timer fire event
		HAL_StartAppTimer(&hih5031Delay);
		return;
	} // WAIT

	if (task ==	HIH5031_GET_HUMIDITY)
	{		
		readBspAdc(hih5031DataCallback, BSP_ADC_CHANNEL1);
		return;
	} // HIH5031_GET_HUMIDITY

}

// eof hih5031.c
